#ifndef PROCESSOR_H
#define PROCESSOR_H
#include <stdlib.h>
#include <glib.h>
#include "log_elem.h"

typedef struct ProcNode {
    /* Node info */
    guint uid;
    gchar * host;
    gchar * name;
    guint pid;
    struct ProcNode * parent;
    gboolean terminated;
    /* Relation */
    GPtrArray  *childs; // ProcNode
    GPtrArray  *ipc_to; // ProcNode
    GPtrArray  *ipc_from; // ProcNode
    GPtrArray  *file_to; // FileNode 
    GPtrArray  *file_from; // FileNode
    GPtrArray  *port_to; // PortNode
    GPtrArray  *port_from;
    GPtrArray  *res_to; // PortNode
    GPtrArray  *res_from;
}ProcNode;

typedef struct PortNode {
    guint uid;
    gchar * host;
    guint port;
    struct ProcNode * ref;
    GPtrArray *proc_from;
    GPtrArray *proc_to;
}PortNode;

typedef struct FileNode {
    guint uid;
    gchar *host;
    gchar * name;
    GPtrArray *proc_to;
    GPtrArray *proc_from;
} FileNode;

typedef struct ResNode {
    guint uid;
    gchar *host;
    gchar * name;
    GPtrArray *proc_to;
    GPtrArray *proc_from;
    void * ref;
} ResNode;

typedef struct Processor {
    GPtrArray *node_alloc;
    guint uid_no;
    GList *file_record; 
    GList *res_record;
    // info->node
    GHashTable *proc;
    GHashTable *port;
    GHashTable *file;
    GHashTable *res;
} Processor;

#define PROCESSOR_UID_INV (guint)-1

int processor_init (Processor **p);

int processor_destruct (Processor *p);

// Proc->Proc
int processor_add_terminate_relation (ProcNode *from, ProcNode *to);
// Proc->Proc
int processor_add_fork_relation (ProcNode *parent, ProcNode *child);
// File->Proc
int processor_add_exec_relation (FileNode *file, ProcNode *proc);
// File->Proc
int processor_add_read_relation (FileNode *file, ProcNode *proc);
// Proc->File
int processor_add_write_relation (ProcNode *proc, FileNode *file);
// Proc->Port
int processor_add_send_relation (ProcNode *proc, PortNode *port);
// port->Proc
int processor_add_recv_relation (PortNode *port, ProcNode *proc);
// Proc->Proc
int processor_add_ipc_relation (ProcNode *from, ProcNode *to);
// Proc->Res
int processor_add_modify_relation (ProcNode *proc, ResNode *res);
// Res->Proc
int processor_add_lookup_relation (ResNode *res, ProcNode *proc);
// port->Proc
int processor_add_refer_relation (PortNode *port, ProcNode *proc);

int processor_add_proc_node (Processor *p, const gchar* host, const gchar *name, guint pid);

int processor_add_port_node (Processor *p, const gchar *host, const guint port);

int processor_add_file_node (Processor *p, const gchar *host, const gchar *name);

int processor_add_res_node (Processor *p, const gchar *host, const gchar *name);

ProcNode * processor_proc_lookup (Processor *p, const gchar* host, const gchar *name, guint pid);

PortNode * processor_port_lookup (Processor *p, const gchar *host, const guint port);

FileNode * processor_file_lookup (Processor *p, const gchar *host, const gchar *name);

ResNode * processor_res_lookup (Processor *p, const gchar *host, const gchar *name);

int processor_process (Processor *p, LogElem *el);

#endif